<template>
  <div class="root">
    <div class="left_box"></div>
    <div class="center_box">
      <div class="canvas_box">
        <canvas id="myCanvas" width="1600" height="900" ref="myCanvas"></canvas>
      </div>
    </div>
    <div class="right_box"></div>
    <div class="mask_model" v-if="openVisible">
      <div class="content_box">
        <div class="top_box">
          <span @click="closeModel"><CloseCircleOutlined/></span>
        </div>
        <div class="center_box">
          <div class="left_content">
            <p class="title">{{ fragmentDetail.title }}</p>
            <p class="content" v-html="fragmentDetail.content"></p>
          </div>
          <div class="right_content">
            <div v-for="item in fragmentDetail.literature" class="line_row">
              <a-image :width="200" :src="item.picUrl" class="img"/>
              <p class="name_title" @click="openPage(item)"
                 :style="{color:isClickId[fragmentDetail.id]?.includes(item.id)?'#d01a37':'gray'}">
                {{ item.name }}
              </p>
            </div>
          </div>
        </div>
        <div class="bottom_box">
          <i class="iconfont icon-suoding" v-if="isLock"></i>
          <i class="iconfont icon-jiesuo" @click="handleOk" v-else></i>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {onMounted, ref} from "vue";
import list from '@/data/data3'
import {CloseCircleOutlined} from '@ant-design/icons-vue'

const myCanvas = ref()
let bg = new URL('../assets/images/photo/拼图1.png', import.meta.url).href
let imgBox2 = [
  {
    id: 1,
    src: new URL('../assets/images/photo/1.png', import.meta.url).href,
    x: 13,
    y: 261,
    pointX: 0,
    pointy: 0,
    canvasDom: null,
    color: '#FF0000',
    name: '碎片1',
    hasAnimated: false,
    linkId: '0F36E9DD-02B3-4CB3-A80A-40ABF04DEA9E',
    title: '当康塔塔遇上最炫民族风',
    isFixed: false, // 新增：标记是否已固定位置
    pathPoint: [{x: 16, y: 267}, {x: 11, y: 510}, {x: 184, y: 407}, {x: 243, y: 262}] // 233*246
  },
  {
    id: 2,
    src: new URL('../assets/images/photo/3.png', import.meta.url).href,
    x: 0,
    y: 562,
    pointX: 0,
    pointy: 450,
    canvasDom: null,
    color: '#0000FF',
    name: '碎片3',
    hasAnimated: false,
    isFixed: false,
    title: "比AI还快的作曲家",
    linkId: '25795346-8455-41E6-9D77-5B8EBCF3C34C',
    pathPoint: [{x: 0, y: 760}, {x: 202, y: 560}, {x: 315, y: 567}, {x: 280, y: 767},]// 313*204
  },
  {
    id: 3,
    src: new URL('../assets/images/photo/7.png', import.meta.url).href,
    x: 30,
    y: 0,
    pointX: 0,
    pointy: 675,
    canvasDom: null,
    color: '#FF8000',
    name: '碎片7',
    hasAnimated: false,
    isFixed: false,
    linkId: '3C9CA55D-CB7D-4EC8-A274-0AB6B12453B1',
    title: "如何在什么都没有的条件下造就一支乐队",
    pathPoint: [{x: 25, y: 0}, {x: 317, y: 210}, {x: 375, y: 168}, {x: 343, y: 5},]// 343*210
  },
  {
    id: 4,
    src: new URL('../assets/images/photo/9.png', import.meta.url).href,
    x: 275,
    y: 569,
    pointX: 0,
    pointy: 225,
    canvasDom: null,
    color: '#00FF80',
    name: '碎片9',
    hasAnimated: false,
    isFixed: false,
    linkId: '51EDD780-8844-402D-A01E-643E8B35FE74',
    title: "90年前的中文版《剧院魅影》",
    pathPoint: [{x: 272, y: 767}, {x: 314, y: 568}, {x: 476, y: 611}, {x: 472, y: 774}]//201*203 ok
  },
  {
    id: 5,
    src: new URL('../assets/images/photo/8.png', import.meta.url).href,
    x: 20,
    y: 0,
    pointX: 1200,
    pointy: 560,
    canvasDom: null,
    color: '#8000FF',
    name: '碎片8',
    hasAnimated: false,
    isFixed: false,
    linkId: '51FC1B6F-CB53-45BA-BC87-E6D51AFF0CD5',
    title: "宁愿失业也不苟且的“无业游民”",
    pathPoint: [{x: 20, y: 0}, {x: 313, y: 211}, {x: 245, y: 257}, {x: 20, y: 263}]//294*266
  },
  {
    id: 6,
    src: new URL('../assets/images/photo/2.png', import.meta.url).href,
    x: 2,
    y: 408,
    pointX: 1200,
    pointy: 740,
    canvasDom: null,
    color: '#00FF00',
    name: '碎片2',
    hasAnimated: false,
    isFixed: false,
    linkId: '5632B0CC-ACE3-4EB5-BB3D-259D4BEC88AE',
    title: "如何在上班时一本正经地抽烟、吃糖",
    pathPoint: [{x: 11, y: 513}, {x: 0, y: 762}, {x: 208, y: 566}, {x: 179, y: 412},]// 205*355  ok
  },

  {
    id: 7,
    src: new URL('../assets/images/photo/4.png', import.meta.url).href,
    x: 176,
    y: 166,
    pointX: 1200,
    pointy: 400,
    canvasDom: null,
    color: '#FFFF00',
    name: '碎片4',
    hasAnimated: false,
    isFixed: false,
    linkId: '6A51394C-4DE3-44B1-A2D9-154BEFE015C4',
    title: "餐具和汽油桶乐器大师",
    pathPoint: [{x: 370, y: 164}, {x: 241, y: 268}, {x: 176, y: 405}, {x: 207, y: 562}, {x: 316, y: 570},] // 195*405
  },
  {
    id: 8,
    src: new URL('../assets/images/photo/5.png', import.meta.url).href,
    x: 342,
    y: 0,
    pointX: 1200,
    pointy: 0,
    canvasDom: null,
    color: '#FF00FF',
    name: '碎片5',
    hasAnimated: false,
    isFixed: false,
    linkId: 'D039D468-A73F-4477-833E-5ED51FB8154D',
    title: "现象级演唱会策划人",
    pathPoint: [{x: 340, y: 0}, {x: 485, y: 0}, {x: 481, y: 301}, {x: 354, y: 337}, {x: 371, y: 166},]// 150*335 ok
  },
  {
    id: 9,
    src: new URL('../assets/images/photo/6.png', import.meta.url).href,
    x: 314,
    y: 300,
    pointX: 1200,
    pointy: 200,
    canvasDom: null,
    color: '#00FFFF',
    name: '碎片6',
    hasAnimated: false,
    isFixed: false,
    linkId: 'F1879521-AABC-4365-AE58-FD344FF17758',
    title: "黄鹤楼下腾起了燃烧的火龙",
    pathPoint: [{x: 350, y: 341}, {x: 311, y: 571}, {x: 480, y: 611}, {x: 482, y: 300},]// 171*310  ok
  },

]
let offscreenCanvasExample = null
let imgBgX = 480, imgBgXIn = imgBgX + 90
let imgBgY = 0, imgBgYIn = imgBgY + 74
let scalePath = 0.4
let ctx = null
let openVisible = ref(false)
// 点击检测相关变量
let hitCanvas = null
let hitCtx = null
let isAnimating = false
let currentItem = {}
let fragmentDetail = ref({})
let isClickId = ref({})
let isLock = ref(true)

// 创建离屏canvas
async function offscreenCanvas() {
  return new Promise((resolve) => {
    if (offscreenCanvasExample) {
      resolve(offscreenCanvasExample)
    } else {
      offscreenCanvasExample = document.createElement('canvas');
      offscreenCanvasExample.width = 667;
      offscreenCanvasExample.height = 897;
      const offscreenCtx = offscreenCanvasExample.getContext('2d');
      let img = new Image();
      img.src = bg;
      img.onload = function () {
        offscreenCtx.drawImage(img, 0, 0);
        resolve(offscreenCanvasExample)
      }
    }
  })
}

// 创建点击检测 Canvas
function createHitCanvas() {
  hitCanvas = document.createElement('canvas')
  hitCanvas.width = 1600
  hitCanvas.height = 900
  hitCtx = hitCanvas.getContext('2d')
}

// 在点击检测Canvas上绘制点击区域
function drawHitRegion(item) {
  hitCtx.fillStyle = item.color
  let width = Math.floor(item.canvasDom.width * scalePath), height = Math.floor(item.canvasDom.height * scalePath)
  hitCtx.fillRect(item.pointX, item.pointy, width, height)
}

// 初始化canvas
async function initCanvas() {
  ctx = myCanvas.value.getContext('2d');
  createHitCanvas(); // 创建点击检测Canvas
  let offscreenExample = await offscreenCanvas()
  ctx.drawImage(offscreenExample, 0, 0, offscreenExample.width, offscreenExample.height, imgBgX, imgBgY, offscreenExample.width, offscreenExample.height)
  for (let i = 0; i < imgBox2.length; i++) {
    const img = new Image();
    img.src = imgBox2[i].src;
    img.onload = function () {
      imgBox2[i].canvasDom = document.createElement('canvas');
      imgBox2[i].canvasDom.width = this.naturalWidth;
      imgBox2[i].canvasDom.height = this.naturalHeight;
      imgBox2[i].x = imgBox2[i].x + imgBgXIn
      imgBox2[i].y = imgBox2[i].y + imgBgYIn
      const offscreenCtx = imgBox2[i].canvasDom.getContext('2d');
      offscreenCtx.drawImage(this, 0, 0);
      createImage(imgBox2[i], i)
      // 在点击检测Canvas上绘制对应颜色的区域
      drawHitRegion(imgBox2[i])
    }
  }
  // 添加点击事件监听
  myCanvas.value.addEventListener('click', handleCanvasClick)
  myCanvas.value.addEventListener('mousemove', handleMouseMove)
  // 更新点击区域
  setTimeout(() => updateHitRegionAfterAnimation(), 1000)
}

// 创建图片
function createImage(item, index) {
  list.data.forEach(c => {
    if (c.id === item.linkId) {
      if (isClickId.value[item.linkId]?.length === c.literature?.length) {
        imgBox2[index].hasAnimated = true
        imgBox2[index].isFixed = true
        let x = item.targetX || item.x, y = item.targetY || item.y
        // 绘制已固定的图片
        ctx.drawImage(item.canvasDom, x, y)
      } else {
        let width = Math.floor(item.canvasDom.width * scalePath), height = Math.floor(item.canvasDom.height * scalePath)
        ctx.drawImage(item.canvasDom, item.pointX, item.pointy, width, height);
        // 创建字体
        createFont(item)
      }
    }
  })

  // let width = Math.floor(item.canvasDom.width * scalePath), height = Math.floor(item.canvasDom.height * scalePath)
  // ctx.drawImage(item.canvasDom, item.pointX, item.pointy, width, height);
}

// 创建字体
function createFont(item) {
  let width = Math.floor(item.canvasDom.width * scalePath), height = Math.floor(item.canvasDom.height * scalePath)
  // 设置字体大小和字体样式
  ctx.font = "18px Arial";
  // 设置文本颜色
  ctx.fillStyle = "#ffffff"; // 黑色
  // 在Canvas上填充文本（实色填充）
  ctx.fillText(item.title, item.pointX + width + 10, item.pointy + height / 2)
}

// 处理Canvas点击事件
function handleCanvasClick(event) {
  if (isAnimating) return // 动画期间不响应点击
  const rect = myCanvas.value.getBoundingClientRect()
  const x = event.clientX - rect.left
  const y = event.clientY - rect.top
  // 获取点击检测Canvas上该位置的颜色
  const pixel = hitCtx.getImageData(x, y, 1, 1).data
  const color = `#${((1 << 24) + (pixel[0] << 16) + (pixel[1] << 8) + pixel[2]).toString(16).slice(1)}`
  // 查找对应的图片
  const clickedItem = imgBox2.find(item => item.color.toUpperCase() === color.toUpperCase())
  if (clickedItem) {
    onImageClick(clickedItem)
  } else {
    console.log('点击了空白区域')
  }
}


function getUrl(path) {
  let url = `../assets/images/second${path}.jpg`
  return new URL(url, import.meta.url).href
}

// 图片点击回调
function onImageClick(item, modelOpen = false) {
  if (modelOpen === false) {
    let data = list.data.find(v => v.id === item.linkId)
    data.literature.forEach(v => {
      v.picUrl = getUrl(v.pic)
    })
    fragmentDetail.value = data
    currentItem = item
    openVisible.value = true
    isLock.value = !(isClickId.value[fragmentDetail.value.id]?.length === fragmentDetail.value?.literature?.length)
    return
  }
  isLock.value = !(isClickId.value[fragmentDetail.value.id]?.length === fragmentDetail.value.literature?.length)
  // 高亮被点击的图片
  highlightImage(item)
  // 可以在这里添加其他业务逻辑，比如开始动画
  if (!item.hasAnimated && !item.isFixed) {
    startPieceAnimation(item)
  } else if (item.isFixed) {
    console.log(`${item.name} 已经固定在目标位置`)
  }
}

// 开始碎片动画
function startPieceAnimation(item) {
  if (item.hasAnimated || item.isFixed) return
  isAnimating = true
  item.hasAnimated = true
  item.startX = item.pointX
  item.startY = item.pointy
  item.targetX = item.x
  item.targetY = item.y
  moveAnimate(item)
}

// 处理鼠标移动事件（改变光标）
function handleMouseMove(event) {
  if (isAnimating) return
  const rect = myCanvas.value.getBoundingClientRect()
  const x = event.clientX - rect.left
  const y = event.clientY - rect.top
  const pixel = hitCtx.getImageData(x, y, 1, 1).data
  const color = `#${((1 << 24) + (pixel[0] << 16) + (pixel[1] << 8) + pixel[2]).toString(16).slice(1)}`
  const hoveredItem = imgBox2.find(item => item.color.toUpperCase() === color.toUpperCase())
  myCanvas.value.style.cursor = hoveredItem ? 'pointer' : 'default'
}

// 重新绘制所有图片
function redrawAllImages() {
  ctx.clearRect(0, 0, 1600, 900)
  ctx.drawImage(offscreenCanvasExample, 0, 0, offscreenCanvasExample.width, offscreenCanvasExample.height, imgBgX, imgBgY, offscreenCanvasExample.width, offscreenCanvasExample.height)

  imgBox2.forEach(item => {
    if (item.isFixed) {
      let x = item.targetX || item.x, y = item.targetY || item.y
      // 已固定的图片：使用目标位置和原始尺寸
      ctx.drawImage(item.canvasDom, x, y)
    } else {
      // 未固定的图片：使用初始位置和缩放尺寸
      let width = Math.floor(item.canvasDom.width * scalePath), height = Math.floor(item.canvasDom.height * scalePath)
      ctx.drawImage(item.canvasDom, item.pointX, item.pointy, width, height)
      // 创建字体
      createFont(item)
    }
  })
}

// 动画函数
function moveAnimate(item) {
  let startTime = null;
  const duration = 1000;

  function animate(currentTime) {
    if (!startTime) {
      startTime = currentTime;
    }
    const elapsed = currentTime - startTime;
    const progress = Math.min(elapsed / duration, 1);
    // 清除画布
    ctx.clearRect(0, 0, 1600, 900);
    // 绘制背景
    ctx.drawImage(offscreenCanvasExample, 0, 0, offscreenCanvasExample.width, offscreenCanvasExample.height, imgBgX, imgBgY, offscreenCanvasExample.width, offscreenCanvasExample.height);
    // 计算当前位置
    const currentX = item.startX + (item.targetX - item.startX) * progress;
    const currentY = item.startY + (item.targetY - item.startY) * progress;
    const startScale = scalePath;
    const targetScale = 1;
    const currentScale = startScale + (targetScale - startScale) * progress;
    const currentWidth = item.canvasDom.width * currentScale;
    const currentHeight = item.canvasDom.height * currentScale;
    // 绘制移动中的图片（带缩放动画）
    ctx.drawImage(item.canvasDom, currentX, currentY, currentWidth, currentHeight);
    // 绘制其他未动画的图片
    imgBox2.forEach(otherItem => {
      if (otherItem !== item && !otherItem.isFixed) {
        let calcWidth = Math.floor(otherItem.canvasDom.width * scalePath)
        let calcHeight = Math.floor(otherItem.canvasDom.height * scalePath)
        ctx.drawImage(otherItem.canvasDom, otherItem.pointX, otherItem.pointy, calcWidth, calcHeight)
        // 创建字体
        createFont(otherItem)
      } else if (otherItem.isFixed) {
        let x = otherItem.targetX || otherItem.x, y = otherItem.targetY || otherItem.y
        // 绘制已固定的图片
        ctx.drawImage(otherItem.canvasDom, x, y)
      }
    });
    // 更新点击检测区域（动画期间）
    updateHitRegionDuringAnimation(item, currentX, currentY, currentWidth, currentHeight);
    if (progress < 1) {
      requestAnimationFrame(animate);
    } else {
      console.log('动画完成！', item.name);
      isAnimating = false;
      item.isFixed = true; // 标记为已固定
      // 动画完成后更新点击检测区域到最终位置
      updateHitRegionAfterAnimation();
      // 重绘所有图片确保固定位置
      redrawAllImages();
    }
  }

  requestAnimationFrame(animate);
}

// 动画期间更新点击检测区域
function updateHitRegionDuringAnimation(item, currentX, currentY, currentWidth, currentHeight) {
  // 清除旧的点击区域
  hitCtx.clearRect(0, 0, 1600, 900);
  // 重新绘制所有静态区域的点击检测
  imgBox2.forEach(imgItem => {
    if (imgItem !== item && !imgItem.isFixed) {
      let width = Math.floor(imgItem.canvasDom.width * scalePath),
          height = Math.floor(imgItem.canvasDom.height * scalePath)
      hitCtx.fillStyle = imgItem.color
      hitCtx.fillRect(imgItem.pointX, imgItem.pointy, width, height)
    } else if (imgItem.isFixed) {
      // 已固定的图片使用目标位置和原始尺寸
      hitCtx.fillStyle = imgItem.color
      hitCtx.fillRect(imgItem.targetX, imgItem.targetY, imgItem.canvasDom.width, imgItem.canvasDom.height)
    }
  });
  // 绘制移动中的图片的点击区域
  hitCtx.fillStyle = item.color
  hitCtx.fillRect(currentX, currentY, currentWidth, currentHeight)
}

// 动画完成后更新点击检测区域
function updateHitRegionAfterAnimation() {
  hitCtx.clearRect(0, 0, 1600, 900);
  // 重新绘制所有点击区域
  imgBox2.forEach(imgItem => {
    if (imgItem.isFixed) {
      // 已固定的图片：使用目标位置和原始尺寸
      hitCtx.fillStyle = imgItem.color;
      let x = imgItem.targetX || imgItem.x, y = imgItem.targetY || imgItem.y
      hitCtx.fillRect(x, y, imgItem.canvasDom.width, imgItem.canvasDom.height);
    } else {
      // // 未固定的图片：使用初始位置和缩放尺寸
      let width = Math.floor(imgItem.canvasDom.width * scalePath),
          height = Math.floor(imgItem.canvasDom.height * scalePath);
      hitCtx.fillStyle = imgItem.color;
      hitCtx.fillRect(imgItem.pointX, imgItem.pointy, width, height);
    }
  });
}

// 高亮被点击的图片
function highlightImage(item) {
  const originalGlobalAlpha = ctx.globalAlpha
  ctx.save()
  ctx.beginPath()
  ctx.translate(imgBgXIn, imgBgYIn)
  item.pathPoint.forEach((item, index) => {
    if (index === 0) {
      ctx.moveTo(item.x, item.y)
    } else {
      ctx.lineTo(item.x, item.y)
    }
  })
  ctx.closePath()
  ctx.strokeStyle = 'yellow'
  ctx.lineWidth = 3
  ctx.stroke()
  ctx.restore()
  ctx.globalAlpha = originalGlobalAlpha
  // 1秒后重绘取消高亮
  setTimeout(() => redrawAllImages(), 800)
}

function handleOk() {
  closeModel()
  if (currentItem.isFixed) {
    return
  }
  onImageClick(currentItem, true)
}

function closeModel() {
  openVisible.value = false
}

function openPage(item) {
  if (isClickId.value[fragmentDetail.value.id]) {
    if (!isClickId.value[fragmentDetail.value.id].includes(item.id)) {
      isClickId.value[fragmentDetail.value.id].push(item.id)
    }
  } else {
    isClickId.value[fragmentDetail.value.id] = [item.id]
  }
  isLock.value = !(isClickId.value[fragmentDetail.value.id].length === fragmentDetail.value.literature.length)
  sessionStorage.setItem('isClickId', JSON.stringify(isClickId.value))
  window.open(item.link, '_blank')
}

onMounted(() => {
  if (sessionStorage.getItem('isClickId')) {
    isClickId.value = JSON.parse(sessionStorage.getItem('isClickId'))
  }
  initCanvas()
})
</script>

<style scoped lang="less">
.root {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-image: url("@/assets/images/bg/bg.png");
  background-repeat: no-repeat;
  background-size: cover;

  .left_box {
    width: calc((100% - 1600px) / 2);
    height: 100%;
  }

  .center_box {
    width: 1600px;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    //background-color: gray;
    position: relative;

    .canvas_box {
      width: 1600px;
      height: 900px;
      position: relative;

      #myCanvas {
        width: 1600px;
        height: 900px;
        position: absolute;
        cursor: default;
      }
    }
  }

  .right_box {
    width: calc((100% - 1000px) / 2);
    height: 100%;
  }
}

p {
  margin: 0;
}

.mask_model {
  position: fixed;
  width: 100vw;
  height: 100vh;
  top: 0;
  left: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(6px);

  .content_box {
    width: 1200px;
    height: 960px;
    background: #faeee1;
    padding: 0 20px 0 20px;

    .top_box {
      width: 100%;
      height: 50px;
      line-height: 50px;
      text-align: right;
      border-bottom: 1px solid lightgrey;

      span {
        font-size: 20px;
        cursor: pointer;
        transition: transform 1s ease-in-out;

        &:hover {
          color: #502f2f;
          transform: rotate(360deg);
        }
      }
    }

    .center_box {
      height: calc(100% - 50px - 60px);
      display: flex;
      width: 100%;
      padding-top: 20px;
      padding-bottom: 20px;

      .left_content {
        width: 600px;
        height: 100%;
        overflow: auto;

        .title {
          font-size: 20px;
          text-align: center;
          font-weight: bolder;
          height: 40px;
        }

        .content {
          white-space: pre-line;
          line-height: 1.4;
          text-align: justify;
          padding: 0 20px;
          font-family: monospace, sans-serif; /* 等宽字体更易对齐（可选） */
        }
      }

      .right_content {
        width: 600px;
        height: 100%;
        overflow: auto;
        padding: 0 20px;

        .line_row {
          display: flex;
          flex-direction: column;
          align-items: center;
          margin-bottom: 24px;

          .name_title {
            margin-top: 6px;
            font-size: 14px;
            text-align: center;
            cursor: pointer;
            text-decoration: underline;
            text-underline-offset: 3px;

            &:hover {
              color: #e7ab33;
            }
          }
        }
      }
    }

    .bottom_box {
      border-top: 1px solid #cccccc;
      height: 60px;
      line-height: 60px;
      width: 100%;
      text-align: center;

      .iconfont {
        font-size: 30px;
      }

      .icon-suoding {
        cursor: not-allowed;
      }

      .icon-jiesuo {
        cursor: pointer;

        &:hover {
          color: #502f2f;
        }
      }
    }
  }
}

</style>
